package com.gzhryc.shared_device.bxscn.code.services;

import com.gzhryc.common.StringTools;
import com.gzhryc.common.exceptions.LogicException;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.jdbc.Conditions;
import com.gzhryc.jdbc.JdbcSession;
import com.gzhryc.jdbc.MultiDBTools;
import com.gzhryc.shared_device.base.IDeviceService;
import com.gzhryc.shared_device.bxscn.code.BXSCNProduceConfig;
import com.gzhryc.shared_device.bxscn.code.dao.PortableEnergyCabinetDao;
import com.gzhryc.shared_device.bxscn.code.dao.db.PortableEnergyCabinet;
import com.gzhryc.shared_device.bxscn.code.dao.enums.PortableEnergyCabinetEnum;
import com.gzhryc.shared_device.bxscn.code.dao.enums.PortableEnergyCabinetSlotEnum;
import com.gzhryc.shared_device.bxscn.code.services.dto.PortableEnergyCabinetSearch;
import com.gzhryc.shared_device.bxscn.code.dao.db.PortableEnergyCabinetSlot;
import com.gzhryc.shared_device.common.device.dao.db.Device;
import com.gzhryc.shared_device.common.device.dao.db.DeviceProduceBatch;
import com.gzhryc.shared_device.common.device.dao.db.DeviceTypeFunc;
import com.gzhryc.shared_device.common.device.services.DeviceService;
import com.gzhryc.shared_device.common.device.services.dto.DeviceSearch;
import org.apache.commons.lang3.StringUtils;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class PortableEnergyCabinetService implements IDeviceService {

	static Logger log = Logger.getLogger(PortableEnergyCabinetService.class);

	public static PortableEnergyCabinetService self() {
		return MultiDBTools.getService(PortableEnergyCabinetService.class, true);
	}

	public static PortableEnergyCabinetService self(String jdbcKey) {
		return MultiDBTools.getService(jdbcKey, PortableEnergyCabinetService.class, true);
	}

	PortableEnergyCabinetDao dao;

	public PortableEnergyCabinetService(String jdbcKey) {
		dao = new PortableEnergyCabinetDao(jdbcKey);
	}

	public List<PortableEnergyCabinet> findJoinBySearch(PortableEnergyCabinetSearch search, Integer pageNo, Integer pageLimit){
		Conditions conditions = dao.buildConditions(search);
		conditions.and().in("deviceSn",search.getDeviceSnList());
		conditions.and().is("device.user_id",search.getUserId());
		conditions.and().is("device.place_id",search.getPlaceId());
		conditions.and().likeBoth("deviceSn",search.getTrim()).or().likeBoth("device.place_name",search.getTrim());
		if(search.getDeploy() != null){
			if(search.getDeploy()){
				conditions.and().isNotNull("device.place_id");
			}else{
				conditions.and().isNull("device.place_id");
			}
		}
		try {
			return dao.findJoinByCondition(conditions,pageNo,pageLimit);
		} catch (SQLException e) {
			log.error(e.getMessage(),e);
		}
		return null;
	}
	
	public List<PortableEnergyCabinet> findJoinBySearch(PortableEnergyCabinetSearch search){
		Conditions conditions = dao.buildConditions(search);
		conditions.and().in("deviceSn",search.getDeviceSnList());
		conditions.and().is("device.user_id",search.getUserId());
		conditions.and().is("device.place_id",search.getPlaceId());
		conditions.and().likeBoth("deviceSn",search.getTrim()).or().likeBoth("device.place_name",search.getTrim());
		if(search.getDeploy() != null){
			if(search.getDeploy()){
				conditions.and().isNotNull("device.place_id");
			}else{
				conditions.and().isNull("device.place_id");
			}
		}
		try {
			return dao.findJoinByCondition(conditions);
		} catch (SQLException e) {
			log.error(e.getMessage(),e);
		}
		return null;
	}

	public Long countJoinBySearch(PortableEnergyCabinetSearch search){
		Conditions conditions = dao.buildConditions(search);
		conditions.and().in("deviceSn",search.getDeviceSnList());
		conditions.and().is("device.user_id",search.getUserId());
		conditions.and().is("device.place_id",search.getPlaceId());
		conditions.and().likeBoth("deviceSn",search.getTrim()).or().likeBoth("device.place_name",search.getTrim());
		if(search.getDeploy() != null){
			if(search.getDeploy()){
				conditions.and().isNotNull("device.place_id");
			}else{
				conditions.and().isNull("device.place_id");
			}
		}
		try {
			return dao.countJoin(conditions);
		} catch (SQLException e) {
			log.error(e.getMessage(),e);
		}
		return 0L;
	}

	public List<PortableEnergyCabinet> findBySearch(PortableEnergyCabinetSearch search, Integer pageNo, Integer pageLimit) {
		Conditions condition = dao.buildConditions(search);
		condition.and().in("deviceSn",search.getDeviceSnList());
		try {
			return dao.findByCondition(condition, pageNo, pageLimit);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}

	public Long countBySearch(PortableEnergyCabinetSearch search) {
		Conditions condition = dao.buildConditions(search);
		try {
			return dao.count(condition);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}

	public List<PortableEnergyCabinet> findByDeviceSnList(List<String> deviceSnList) {
		if (deviceSnList != null && deviceSnList.size() > 0) {
			Conditions conditions = new Conditions(PortableEnergyCabinet.class);
			conditions.and().in("deviceSn", deviceSnList);
			try {
				return dao.findByCondition(conditions);
			} catch (SQLException e) {
				log.error(e.getMessage(), e);
			}
		}
		return null;
	}

	public PortableEnergyCabinet getByDeviceSn(String deviceSn) {
		if (StringUtils.isNotBlank(deviceSn)) {
			Conditions condition = new Conditions(PortableEnergyCabinet.class);
			condition.and().is("deviceSn", deviceSn);
			try {
				return dao.get(condition);
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	public PortableEnergyCabinet getJoinByDeviceSn(String deviceSn) {
		if (StringUtils.isNotBlank(deviceSn)) {
			Conditions condition = new Conditions(PortableEnergyCabinet.class);
			condition.and().is("deviceSn", deviceSn);
			try {
				return dao.getJoin(condition);
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	public boolean add(PortableEnergyCabinet batteryCabinet) throws LogicException {
		PortableEnergyCabinet entity = getByDeviceSn(batteryCabinet.getDeviceSn());
		if (entity != null) {
			throw new LogicException("机柜已存在");
		}
		batteryCabinet.setCreateDate(new Date());

		Device device = DeviceService.self().getByDeviceSn(batteryCabinet.getDeviceSn());
		if (device != null) {
			throw new LogicException("设备索引已存在");
		}

		JdbcSession.begin();
		try {
			if (dao.insert(batteryCabinet) > 0) {
				device = new Device();
				device.setDeviceSn(batteryCabinet.getDeviceSn());
				device.setDeviceTypeId(batteryCabinet.getDeviceTypeId());
				device.setDeviceTypeName(batteryCabinet.getDeviceTypeName());
				if (DeviceService.self().add(device)) {
					JdbcSession.commit();
					return true;
				}
			}
		} catch (SQLException e) {
			log.error(e.getMessage());
		} finally {
			JdbcSession.end();
		}
		return false;
	}

	public boolean updateSlotTotal(String deviceSn, Integer slotTotal) {
		if (StringUtils.isNotBlank(deviceSn)) {
			PortableEnergyCabinet cdb = new PortableEnergyCabinet();
			cdb.setDeviceSn(deviceSn);
			cdb.setSlotTotal(slotTotal);
			try {
				return dao.updateNotNull(cdb) > 0;
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return false;
	}

	public boolean updateCardNum(String deviceSn, String cardNum) {
		if (StringUtils.isNotBlank(deviceSn) && StringUtils.isNotBlank(cardNum)) {
			PortableEnergyCabinet updateEntity = new PortableEnergyCabinet();
			updateEntity.setDeviceSn(deviceSn);
			updateEntity.setCardNum(cardNum);

			try {
				return dao.updateNotNull(updateEntity) > 0;
			} catch (SQLException e) {
				log.error(e.getMessage(), e);
			}
		}
		return false;
	}

	public boolean updateDeviceTypeName(String deviceTypeId,String deviceTypeName){
		if(StringTools.isNotBlank(deviceTypeId) && StringTools.isNotBlank(deviceTypeName)){
			Conditions conditions = new Conditions(PortableEnergyCabinet.class);
			conditions.and().is("deviceTypeId",deviceTypeId);

			PortableEnergyCabinet updateEntity = new PortableEnergyCabinet();
			updateEntity.setDeviceTypeName(deviceTypeName);

			try {
				return dao.updateNotNull(updateEntity,conditions) >= 0;
			} catch (SQLException e) {
				log.error(e.getMessage(),e);
			}
		}
		return false;
	}

	public boolean produceDevice(DeviceProduceBatch produceBatch, DeviceTypeFunc deviceTypeFunc, BXSCNProduceConfig produceConfig){
		Integer iotType = Integer.valueOf(produceConfig.getIotType());
		Long iotNodeId = Long.valueOf(produceConfig.getIotNodeId());
		DeviceSearch search = new DeviceSearch();
		search.setBatchId(produceBatch.getBatchId());
		Integer pageNo = 1;
		Integer pageLimit = 300;
		List<Device> deviceList = DeviceService.self().findBySearch(search,pageNo,pageLimit);
		List<PortableEnergyCabinet> data = new ArrayList<>();
		List<PortableEnergyCabinetSlot> slotData = new ArrayList<>();
		while (deviceList != null && deviceList.size() > 0){
			for(Device device : deviceList) {
				PortableEnergyCabinet batteryCabinet = new PortableEnergyCabinet();
				batteryCabinet.setDeviceSn(device.getDeviceSn());
				batteryCabinet.setDeviceTypeId(device.getDeviceTypeId());
				batteryCabinet.setDeviceTypeName(device.getDeviceTypeName());
				batteryCabinet.setSlotTotal(deviceTypeFunc.getSlotTotal());
				batteryCabinet.setIotType(iotType);
				batteryCabinet.setIotNodeId(iotNodeId);
				batteryCabinet.setProtocolType(deviceTypeFunc.getProtocolType());
				batteryCabinet.setCreateDate(new Date());
				data.add(batteryCabinet);

				//卡槽
				for (int i = 1; i <= batteryCabinet.getSlotTotal(); i++) {
					PortableEnergyCabinetSlot slot = new PortableEnergyCabinetSlot();
					slot.setDeviceSn(batteryCabinet.getDeviceSn());
					slot.setSlotNum(i);
					slot.setState(PortableEnergyCabinetSlotEnum.State.Normal.index());
					slot.setCreateDate(new Date());
					slotData.add(slot);
				}
			}
			pageNo = pageNo + 1;
			deviceList = DeviceService.self().findBySearch(search,pageNo,pageLimit);
		}

		JdbcSession.begin();
		try {
			if(dao.insert(data) > 0){
				if(PortableEnergyCabinetSlotService.self().add(slotData)){
					JdbcSession.commit();
					return true;
				}
			}
		} catch (SQLException e) {
			log.error(e.getMessage(),e);
		} finally {
			JdbcSession.end();
		}
		return false;
	}

	/**
	 * 设备心跳
	 * 
	 * @param deviceSn
	 * @param rssi
	 * @param iccid
	 * @param versionNumber
	 * @return
	 */
	public boolean heart(String deviceSn, String versionNumber, Integer rssi, String iccid) {
		if (StringUtils.isNotBlank(deviceSn)) {
			try {
				Conditions condition = new Conditions(PortableEnergyCabinet.class);
				condition.and().is("deviceSn", deviceSn);

				PortableEnergyCabinet updateEntity = new PortableEnergyCabinet();
				updateEntity.setState(PortableEnergyCabinetEnum.State.Online.index());
				updateEntity.setVersionNumber(versionNumber);
				updateEntity.setRssi(rssi);
				updateEntity.setIccid(iccid);
				if (dao.updateNotNull(updateEntity, condition) > 0) {
					return true;
				}
			} catch (SQLException e) {
				log.error(e.getMessage());
			}
		}
		return false;
	}

	/**
	 * 设备上线
	 * 
	 * @param deviceSn
	 * @return
	 */
	public boolean online(String deviceSn, String versionNumber, String imsi, String iccid, Integer rssi) {
		if (StringUtils.isNotBlank(deviceSn)) {
			try {
				PortableEnergyCabinet updateEntity = new PortableEnergyCabinet();
				updateEntity.setDeviceSn(deviceSn);
				updateEntity.setVersionNumber(versionNumber);
				updateEntity.setImsi(imsi);
				updateEntity.setIccid(iccid);
				updateEntity.setRssi(rssi);
				updateEntity.setState(PortableEnergyCabinetEnum.State.Online.index());
				if (dao.updateNotNull(updateEntity) > 0) {
					return true;
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return false;
	}

	/**
	 * 设备离线
	 * 
	 * @param deviceSn
	 * @return
	 */
	public boolean offline(String deviceSn) {
		if (StringUtils.isNotBlank(deviceSn)) {
			try {
				PortableEnergyCabinet updateEntity = new PortableEnergyCabinet();
				updateEntity.setDeviceSn(deviceSn);
				updateEntity.setState(PortableEnergyCabinetEnum.State.Offline.index());
				updateEntity.setLastOfflineDate(new Date());
				if (dao.updateNotNull(updateEntity) > 0) {
					return true;
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return false;
	}

	/**
	 * 全部设备离线
	 * 
	 * @return
	 */
	public void offlineAll() {
		Conditions conditions = new Conditions(PortableEnergyCabinet.class);
		conditions.and().is("state", PortableEnergyCabinetEnum.State.Online.index());

		PortableEnergyCabinet batteryCabinet = new PortableEnergyCabinet();
		batteryCabinet.setState(PortableEnergyCabinetEnum.State.Offline.index());
		try {
			dao.updateNotNull(batteryCabinet, conditions);
		} catch (SQLException e) {
			log.error(e.getMessage(), e);
		}
	}

	@Override
	public boolean deleteByDeviceSn(String deviceSn) throws LogicException {
		if(StringTools.isNotBlank(deviceSn)) {
			Conditions condition = new Conditions(PortableEnergyCabinet.class);
			condition.and().is("deviceSn", deviceSn);

			JdbcSession.begin();
			try {
				if(dao.deleteByCondition(condition) > 0){
					if(PortableEnergyCabinetSlotService.self().deleteByDeviceSn(deviceSn)){
						JdbcSession.commit();
						return true;
					}
				}else {
					PortableEnergyCabinet portableEnergyCabinet = getByDeviceSn(deviceSn);
					if(portableEnergyCabinet == null) {
						log.info("{{0}}共享便携式电池已删除", deviceSn);
						if (PortableEnergyCabinetSlotService.self().deleteByDeviceSn(deviceSn)) {    //执行一次删除，避免脏数据
							JdbcSession.commit();
							return true;
						}
					}
				}
			} catch (SQLException e) {
				log.error(e.getMessage(),e);
			}finally {
				JdbcSession.end();
			}
		}
		return false;
	}
}
